feat(linearagent): Linear Agent Session webhook types + API client (RIG-2717 T1/T2) - #638
Merged
Merged
Conversation
|
Compass engineering docs preview: https://compass-server-rig-2717-stor.compass-eng-docs.pages.dev Deployed from |
rigel-mintaka
force-pushed
the
compass-server/rig-2717-linearagent
branch
from
August 26, 2026 04:01
15102f9 to
012b113
Compare
rigel-mintaka
force-pushed
the
compass-server/rig-2717-store
branch
from
August 26, 2026 04:02
276657c to
dd0e7e7
Compare
…IG-2717 T1/T2) New go/internal/linearagent package for the Linear Agent Session responder: - webhook.go (T1): SessionEvent envelope (AgentSessionEventWebhookPayload shape), ParseSessionEvent, VerifySignature (constant-time HMAC-SHA256 over the raw body, false on hex-decode error), CheckTimestamp (bidirectional skew on the ms-epoch webhookTimestamp). - client.go (T2): client-credentials TokenSource (in-memory cache, singleflight-coalesced re-mint, pinned scope), and the Client emitter wrapping agentActivityCreate (the thought ack) + agentSessionUpdate (the external-URL deep link), re-minting once and retrying once on 401. Pure/unit-tested against httptest; no HTTP handler, store, or dispatcher yet (sibling tasks). Builds against the frozen record docs/designs/product/compass-linear-agent-responder/design.md. Ref: RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build>
…717 T3/T3a) Persistence for the Linear Agent Session responder: - T3: new 0002_linear_agent_sessions migration (association row keyed on the Linear session id; no dedup column — dedup is the comms rail's client_request_id), UpsertLinearAgentSession (ON CONFLICT DO NOTHING, created=false on replay) + LinearAgentSession lookup, and AuthoredArtifactByCoordinate (by-coordinate ownership read the router needs). - T3a: generalize the reserved system-account seed to a shared ensureSystemSubtypeAccount, add EnsureLinearBridgeAccount seeding @linear as a second system-subtype account, and reserve the 'linear' handle against user/agent registration. pgtest-covered (upsert/replay/lookup, by-coordinate hit/miss, @linear idempotent seed + structural exclusions + reserved-handle guard). Ref: RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build>
…ration (RIG-2717) Matt's ruling on #638: collapse the linear_agent_sessions table into the single existing 0001_init.sql migration rather than shipping an incremental 0002 — Compass isn't deployed yet, so there's no data to migrate and no reason for a versioned increment. Moves the CREATE TABLE linear_agent_sessions into 0001_init.sql (adapting the file-header comment), deletes 0002_linear_agent_sessions.sql, and updates the pgtest header comment that named the '0002 table'. Pure DDL relocation — no backfill (the table carried none), no schema shape change; the migration loader embeds migrations/*.sql and enforces a contiguous 1..N sequence, so a single 0001 stays valid. Refs RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build>
rigel-mintaka
force-pushed
the
compass-server/rig-2717-store
branch
from
August 27, 2026 18:06
dd0e7e7 to
9e905be
Compare
mattwilkinsonn
approved these changes
Aug 27, 2026
mattwilkinsonn
added a commit
that referenced
this pull request
Aug 27, 2026
… T5) (#639) * feat(linearagent): Linear Agent Session webhook types + API client (RIG-2717 T1/T2) New go/internal/linearagent package for the Linear Agent Session responder: - webhook.go (T1): SessionEvent envelope (AgentSessionEventWebhookPayload shape), ParseSessionEvent, VerifySignature (constant-time HMAC-SHA256 over the raw body, false on hex-decode error), CheckTimestamp (bidirectional skew on the ms-epoch webhookTimestamp). - client.go (T2): client-credentials TokenSource (in-memory cache, singleflight-coalesced re-mint, pinned scope), and the Client emitter wrapping agentActivityCreate (the thought ack) + agentSessionUpdate (the external-URL deep link), re-minting once and retrying once on 401. Pure/unit-tested against httptest; no HTTP handler, store, or dispatcher yet (sibling tasks). Builds against the frozen record docs/designs/product/compass-linear-agent-responder/design.md. Ref: RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build> * feat(store): linear_agent_sessions table + @linear bridge seed (RIG-2717 T3/T3a) Persistence for the Linear Agent Session responder: - T3: new 0002_linear_agent_sessions migration (association row keyed on the Linear session id; no dedup column — dedup is the comms rail's client_request_id), UpsertLinearAgentSession (ON CONFLICT DO NOTHING, created=false on replay) + LinearAgentSession lookup, and AuthoredArtifactByCoordinate (by-coordinate ownership read the router needs). - T3a: generalize the reserved system-account seed to a shared ensureSystemSubtypeAccount, add EnsureLinearBridgeAccount seeding @linear as a second system-subtype account, and reserve the 'linear' handle against user/agent registration. pgtest-covered (upsert/replay/lookup, by-coordinate hit/miss, @linear idempotent seed + structural exclusions + reserved-handle guard). Ref: RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build> * feat(store): fold linear_agent_sessions into 0001, no incremental migration (RIG-2717) Matt's ruling on #638: collapse the linear_agent_sessions table into the single existing 0001_init.sql migration rather than shipping an incremental 0002 — Compass isn't deployed yet, so there's no data to migrate and no reason for a versioned increment. Moves the CREATE TABLE linear_agent_sessions into 0001_init.sql (adapting the file-header comment), deletes 0002_linear_agent_sessions.sql, and updates the pgtest header comment that named the '0002 table'. Pure DDL relocation — no backfill (the table carried none), no schema shape change; the migration loader embeds migrations/*.sql and enforces a contiguous 1..N sequence, so a single 0001 stays valid. Refs RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build> * feat(server): per-deployment public URL + deep-link builder (RIG-2717 T5) Add ServeConfig.PublicURL (--public-url flag / $COMPASS_PUBLIC_URL, flag->env->default https://compass.rigel.build), and deepLinkFor(base, channelID) building the 'Open in Compass' deep link to a Manager's home channel (the UI hash route), with requirePublicURL as the legible boot guard for a Linear-webhook-consuming deploy. Threaded through cmd/compass-server (the server entrypoint) — not cmd/compass (the operator CLI, which does no server construction). Ref: RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build> * feat(server): no default public URL — managed host is not a repo concern (RIG-2717) Matt's ruling on #639: don't default --public-url to the managed-service host (https://compass.rigel.build). That host is where the managed deployment lives, which never lives in this repo; baking it as the fallback means a self-host/dev deploy that forgets the flag silently emits deep links to the managed host. Removes the defaultPublicURL constant; PublicURL now resolves from --public-url then $COMPASS_PUBLIC_URL with no default (empty when unset). The existing requirePublicURL boot guard already rejects an empty base for a webhook-consuming deploy and yields relative fragments for socket-only local — so no-default is the right shape (a dummy non-empty URL would instead DEFEAT that guard). Updates the flag help + the ServeConfig/boot-log/boot-guard doc comments, and neutralizes the managed host out of deeplink_test.go's sample URLs. Refs RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build> * docs(server): drop vestigial managed-default clause from firstNonEmpty doc (RIG-2717) Review finding (#639, low): after removing the managed default, firstNonEmpty's doc comment still described a 'where a managed default follows, flag-then-env-then-default' precedence that no remaining caller uses (every caller is flag-then-env only) — muddying the very ruling this branch implements. Simplified to describe only the flag-then-env precedence in use. Comment-only. Refs RIG-2717 Co-authored-by: Matt Wilkinson <matt@rigel.build> --------- Co-authored-by: Matt Wilkinson <matt@rigel.build>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR is part of a stack containing 2 PRs:
mainPersistence for the Linear Agent Session responder — folded into the single baseline migration per Matt's ruling on this PR.
linear_agent_sessionstable folds directly into0001_init.sql(no incremental0002): Compass isn't deployed yet, so there's no data to preserve and no reason to ship an incremental migration. The association row is keyed on the Linear session id; there's no dedup column — dedup is the comms rail'sclient_request_id.UpsertLinearAgentSession(ON CONFLICT DO NOTHING,created=falseon replay),LinearAgentSessionlookup, andAuthoredArtifactByCoordinate(the by-coordinate ownership read the router needs).ensureSystemSubtypeAccount, seeds@linearas a second system-subtype account, and reserves thelinearhandle against user/agent registration.pgtest-covered: upsert/replay/lookup, by-coordinate hit/miss,
@linearidempotent seed + structural exclusions + reserved-handle guard.Spec-impact: none. Refs RIG-2717
Co-authored-by: Matt Wilkinson matt@rigel.build